import {expect} from 'chai';
import * as sinon from 'sinon';
import * as step from '@ali/flow-step-toolkit'
// @ts-ignore
import {PutObjectResult} from './storage'

const proxyquire = require('proxyquire');

// @ts-ignore
import {RemoteStorage} from '../src/storage';
// @ts-ignore
import {CACHE_FILE_MAX_SIZE} from "../src/cache";
// @ts-ignore
import {mockIParams} from './cache.spec';

let remoteStorage: RemoteStorage;
let statStub: sinon.SinonStub;
let putStub: sinon.SinonStub;
let getStub: sinon.SinonStub;

let sandbox = sinon.createSandbox();
let stepExecStub: sinon.SinonStub;

describe('upload', () => {
    beforeEach(() => {
        stepExecStub = sandbox.stub(step.exec, 'call').returns(Promise.resolve(0));

        statStub = sandbox.stub();
        putStub = sandbox.stub();
        getStub = sandbox.stub();
        remoteStorage = {
            stat: statStub,
            put: putStub,
            get: getStub
        }
    });

    afterEach(() => {
        sandbox.restore();
    });


    const fsStub = {
        statSync: sinon.stub(),
        existsSync: sinon.stub(),
    };
    const {upload} = proxyquire('../src/upload', {
        fs: fsStub
    })

    it('should skip upload when find no folder to cache', async () => {
        const params = mockIParams()
        params.archivePath = '/path/not_exist / /root /root/workspace /root/cache/..';
        params.workspace = '/path/to/workspace';
        params.fileID = 'file-id';
        const artifactFullName = 'artifact-full-name';
        fsStub.existsSync.returns(false);

        await upload(remoteStorage, params, artifactFullName);

        expect(putStub.called).to.be.false;
    })

    it('should upload cache file successfully', async () => {
        const params = mockIParams()
        params.archivePath = '/path/to/archive';
        params.workspace = '/path/to/workspace';
        params.fileID = 'file-id';
        const artifactFullName = 'artifact-full-name';
        fsStub.existsSync.returns(true);

        const putObjectResult: PutObjectResult = {
            name: '',
            url: '',
            data: {},
            res: {
                status: 200,
                size: 0,
                rt: 0
            }
        };
        putStub.resolves(putObjectResult);

        fsStub.statSync.returns({size: 100});
        await upload(remoteStorage, params, artifactFullName);

        expect(putStub.calledOnceWith(params.fileID, artifactFullName, {
            headers: {
                'x-oss-tagging': 'caches=true',
            }
        })).to.be.true;
    });

    it('should skip cache upload if cache file size exceeds max size limit', async () => {
        const params = mockIParams()
        params.archivePath = '/path/to/archive';
        params.workspace = '/path/to/workspace';
        params.fileID = 'file-id';
        const artifactFullName = 'artifact-full-name';
        fsStub.existsSync.returns(true);

        fsStub.statSync.returns({size: Number(CACHE_FILE_MAX_SIZE + 100)});

        await upload(remoteStorage, params, artifactFullName);

        expect(putStub.called).to.be.false;
    });
});
